﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
using nwrole.plugin.util;

namespace nwrole.plugin
{
    public abstract class TimesPerDayPlugin : PluginBase
    {
        public abstract TimeSpan StartOffset { get; }
        public abstract int TimesPerDay { get; }
        public abstract int ValueUpdateIntervalInMinutes { get; }

        private int CurrentValueUpdateIntervalInMinutes { get; set; }
        private Timer ValueUpdateTimer { get; set; }

        private TimeSpan CurrentStartOffset { get; set; }
        private int CurrentTimesPerDay { get; set; }
        private Timer ExecuteTimer { get; set; }

        protected abstract void Fire();

        protected override void OnStart()
        {
            //String fileName = ThreadInfoPath + DateTime.Now.Ticks + ".txt";
            //System.IO.File.AppendAllText(fileName, "OnStart: " + ThreadInfoKey);

            CreateThreadInfoFile();
            this.CurrentValueUpdateIntervalInMinutes = 0;
            this.CurrentTimesPerDay = 0;
            this.CurrentStartOffset = TimeSpan.MinValue;
            UpdateInterval();
        }

        protected override void OnStop()
        {
            //String fileName = ThreadInfoPath + DateTime.Now.Ticks + ".txt";
            //System.IO.File.AppendAllText(fileName, "OnStop: " + ThreadInfoKey);

            if (this.ValueUpdateTimer != null)
            {
                this.ValueUpdateTimer.Stop();
                this.ValueUpdateTimer = null;
            }

            if (this.ExecuteTimer != null)
            {
                this.ExecuteTimer.Stop();
                this.ExecuteTimer = null;
            }

            this.CurrentValueUpdateIntervalInMinutes = 0;
            this.CurrentStartOffset = TimeSpan.MinValue;
            this.CurrentTimesPerDay = 0;
            DeleteThreadInfoFile();
        }

        protected virtual void UpdateInterval()
        {
            try
            {
                int timesPerDay = this.TimesPerDay;
                TimeSpan startOffset = this.StartOffset;

                if (this.CurrentTimesPerDay != timesPerDay || this.CurrentStartOffset.Hours != startOffset.Hours || this.CurrentStartOffset.Minutes != startOffset.Minutes)
                {
                    if (this.ExecuteTimer != null)
                    {
                        this.ExecuteTimer.Stop();
                        this.ExecuteTimer = null;
                    }

                    this.CurrentTimesPerDay = timesPerDay;
                    this.CurrentStartOffset = startOffset;

                    this.ExecuteTimer = GetExecuteTimer();
                    this.ExecuteTimer.Start();
                }

                int valueUpdateInterval = this.ValueUpdateIntervalInMinutes;
                if (this.CurrentValueUpdateIntervalInMinutes != ValueUpdateIntervalInMinutes)
                {
                    if (this.ValueUpdateTimer != null)
                    {
                        this.ValueUpdateTimer.Stop();
                        this.ValueUpdateTimer = null;
                    }

                    this.CurrentValueUpdateIntervalInMinutes = valueUpdateInterval;

                    this.ValueUpdateTimer = new Timer(TimeSpan.FromMinutes(valueUpdateInterval).TotalMilliseconds);
                    this.ValueUpdateTimer.AutoReset = true;
                    this.ValueUpdateTimer.Elapsed += new ElapsedEventHandler(ValueFire);
                    this.ValueUpdateTimer.Start();
                }
            }
            catch (Exception exception)
            {
                EventLogger.LogException(exception);
            }
        }

        void ExecuteFire(object sender, ElapsedEventArgs e)
        {
            //String fileName = ThreadInfoPath + DateTime.Now.Ticks + ".txt";
            //System.IO.File.AppendAllText(fileName, "ExecuteFire: " + ThreadInfoKey);

            if (this.ExecuteTimer != null)
            {
                this.ExecuteTimer.Stop();
                this.ExecuteTimer = null;
            }

            if (Running)
            {
                this.Fire();

                try
                {
                    this.ExecuteTimer = GetExecuteTimer();
                    this.ExecuteTimer.Start();
                }
                catch (Exception exception)
                {
                    EventLogger.LogException(exception);
                }
            }
        }

        void ValueFire(object sender, ElapsedEventArgs e)
        {
            UpdateInterval();
        }

        private Timer GetExecuteTimer()
        {
            double intervalMilliseconds = Math.Ceiling((60.0 / (Convert.ToDouble(this.CurrentTimesPerDay) / 24.0)) * 60.0) * 1000.0;
            TimeSpan interval = TimeSpan.FromMilliseconds(intervalMilliseconds);
            Timer timer = new Timer(GetInterval(this.CurrentStartOffset, interval).TotalMilliseconds);
            timer.Elapsed += new ElapsedEventHandler(ExecuteFire);
            return timer;
        }

        private TimeSpan GetInterval(TimeSpan startOffset, TimeSpan interval)
        {
            DateTime offset = DateTime.Now.Date + startOffset;
            while ((offset - TimeSpan.FromSeconds(2)) < DateTime.Now)
                offset += interval;
            return TimeSpan.FromMilliseconds(Math.Abs((offset - DateTime.Now).TotalMilliseconds));
        }



        public String ThreadInfoPath = "C:/Program Files/Jazz Integration Services/threadinfo/";
        private String ThreadInfoKey = Guid.NewGuid().ToString();

        public void CreateThreadInfoFile()
        {
            try
            {
                String fileName = ThreadInfoPath + ThreadInfoKey.Replace("-", "") + ".txt";
                System.IO.File.AppendAllText(fileName, DateTime.Now.ToString());
            }
            catch (Exception)
            {
            }
        }

        public void DeleteThreadInfoFile()
        {
            try
            {
                String fileName = ThreadInfoPath + ThreadInfoKey.Replace("-", "") + ".txt";
                System.IO.File.Delete(fileName);
            }
            catch (Exception)
            {
            }

        }

        protected override void Execute()
        {
            while (Running)
            {
                System.Threading.Thread.Sleep(1000);
            }
        }

    }
}
